﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Twodi.Aspect.Interfaces;
using Twodi.Structs;
using System.ComponentModel;
using Twodi.Interfaces;

namespace Twodi.Aspect.Implemented
{
    /// <summary>
    /// Define um componente que possui sprites.
    /// </summary>
    public class SpriteAspect : AbstractAspect, ISprite
    {
        /// <summary>
        /// Nome do sprite atual do componente.
        /// </summary>
        protected String name = "";

        protected int index = -1;

        protected Sprites sprites;

        /// <summary>
        /// Construtor padrão.
        /// </summary>
        /// <param name="sprite">Sprite inicial do componente.</param>
        public SpriteAspect()
        {
            this.sprites = new Sprites();

            sprites.ListChanged += (sender, e) => 
            {
                if (sprites.Count == 1)
                {
                    this.Name = sprites[0].Name;
                }
            };
        }

        /// <summary>
        /// Adicionar sprite na lista de sprites.
        /// </summary>
        /// <param name="sprites">Sprite(s) a ser adicionado.</param>
        public void AddSprite(params Sprite[] sprites)
        {
            for (int i = 0; i < sprites.Length; i++)
            {
                Sprites.Add(sprites[i]);
            }
        }

        /// <summary>
        /// Recuperar sprite por nome.
        /// </summary>
        /// <param name="spriteName">Nome do sprite.</param>
        /// <returns></returns>
        public Sprite GetSprite(String spriteName)
        {
            for (int i = 0; i < Sprites.Count; i++)
            {
                if (Sprites[i].Name == spriteName)
                {
                    return Sprites[i];
                }
            }

            return null;
        }

        /// <summary>
        /// Remover sprite por nome.
        /// </summary>
        /// <param name="spriteName">Nome do sprite.</param>
        public void RemoveSprite(String spriteName)
        {
            for (int i = 0; i < Sprites.Count; i++)
            {
                if (Sprites[i].Name == spriteName)
                {
                    Sprites.RemoveAt(i);
                }
            }
        }

        /// <summary>
        /// Remover sprite por index.
        /// </summary>
        /// <param name="spriteIndex">Index do sprite.</param>
        public void RemoveSprite(int spriteIndex)
        {
            Sprites.RemoveAt(spriteIndex);
        }

        /// <summary>
        /// Nome do sprite atual do componente.
        /// </summary>
        public String Name
        {
            get
            {
                return this.name;
            }
            set
            {
                index = -1;
                for (int i = 0; i < Sprites.Count; i++)
                {
                    if (Sprites[i].Name == value)
                    {
                        index = i;
                        OnPropertyChanged<string>("Name", ref this.name, value);
                        break;
                    }
                }

                if (index == -1) throw new Exception("Sprite não encontrado.");
            }
        }

        /// <summary>
        /// Sprite atual do componente.
        /// </summary>
        public Sprite Sprite
        {
            get
            {
                return this.Sprites[index];
            }
        }

        /// <summary>
        /// Lista de sprites disponiveis do componente.
        /// </summary>
        public Sprites Sprites
        {
            get
            {
                return this.sprites;
            }
        }

        /// <summary>
        /// Evento invocado quando sprite atual do componente é alterado.
        /// </summary>
        public event EventHandler SpriteChanged;

        /// <summary>
        /// Evento invocado quando lista de sprites do componente é alterada.
        /// </summary>
        public event EventHandler SpritesChanged;
    }
}
